﻿using AutoMapper;
using Paperless.Models;
using Paperless.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Paperless.Entities;

namespace Paperless.Controllers
{
    public abstract class BaseApiController<T, TModel> : ApiController where T: Entities.Entity where TModel: BaseModel
    {
        public IRepository<T> Repository { get; set; }
        public UserManager<User> UserManager { get; private set; }

        public BaseApiController(IRepository<T> repository)
        {
            Repository = repository;
            UserManager = new UserManager<User>(new UserStore<User>(new PaperlessContext()));
        }

        public virtual IHttpActionResult Get()
        {
            var entities = Repository.DbSet().OrderByDescending(x => x.UpdatedDate).ThenByDescending(x => x.CreatedDate);
            var model = Mapper.Map<IEnumerable<TModel>>(entities);
            return Ok(model);
        }

        public virtual async Task<IHttpActionResult> GetBy(long id)
        {
            var entity = await Repository.GetBy(id);

            var model = Mapper.Map<TModel>(entity);

            if (model == null)
            {
                return NotFound();
            }

            return Ok(model);
        }

        public virtual async Task<IHttpActionResult> Post(TModel model)
        {
            model.CreatedBy = User.Identity.GetUserName();
            model.CreatedDate = DateTime.Now;

            var entity = Mapper.Map<T>(model);

            try
            {
                await Repository.Add(entity);
            }
            catch (Exception e)
            {
                return InternalServerError(e);
            }

            return Ok(entity.Id);
        }

        public virtual async Task<IHttpActionResult> Put(TModel model)
        {
            model.UpdatedBy = User.Identity.GetUserName();
            model.UpdatedDate = DateTime.Now;

            var entity = Mapper.Map<T>(model);

            try
            {
                await Repository.Update(entity);
            }
            catch (Exception e)
            {
                return InternalServerError(e);
            }

            return Ok();
        }

        public virtual async Task<IHttpActionResult> Delete(long id)
        {
            try
            {
                await Repository.Remove(id);
            }
            catch (Exception e)
            {
                return InternalServerError(e);
            }

            return Ok();
        }
    }
}
